#include "./../../../include/online/Reactor/TcpConnection.h"
#include <sstream>
#include <iostream>

// 构造函数：通过套接字文件描述符初始化TcpConnection对象
TcpConnection::TcpConnection(int fd,EventLoop* eventloop)
: _sockIO(fd) // 初始化SockIO对象，处理读写操作
,_sock(fd) // 初始化Socket对象，管理底层套接字
,_localAddr(getLocalAddr()) // 获取本端网络地址信息
,_peerAddr(getPeerAddr()) // 获取对端网络地址信息
,_eventloop(eventloop)
{

}

// 析构函数：析构TcpConnection对象
TcpConnection::~TcpConnection()
{
    // 这里没有做任何资源清理工作，因为Socket和SockIO的资源会在其析构函数中自动清理
}

// 接收消息：读取一行数据并返回
string TcpConnection::receive()
{
    char buf[65536] = {0};              // 定义一个缓冲区，接收最大64KB的数据
    _sockIO.readLine(buf, sizeof(buf)); // 从套接字读取一行数据
    return string(buf);                 // 返回接收到的消息（转换为字符串）
}

// 发送消息：将消息发送到对端
void TcpConnection::send(const string &msg)
{
    _sockIO.writen(msg.c_str(), msg.size()); // 使用SockIO将消息写入套接字
}

// 此处参数中的msg就是线程池中的线程处理好之后的
// 可以发送给客户端的msg
// 还需要将发送数据的能力的TcpConnection的对象也发给
// EventLoop,只有这样才能让EventLoop具备发送数据的能力
// 还需要将TcpConnection发送数据的函数也发给EventLoop
void TcpConnection::sendInLoop(const string& msg)
{
    // sendInLoop函数需要将线程池中的线程处理好之后的数据
    // msg,以及发送数据的连接TcpConnection的对象，以及
    // 发送数据的能力函数send都一次性打包发给EventLoop,
    // （即就是就处理之后的数据，这条TcpConnection连接对象，
    // 以及TcpConnnection对象发送数据的能力函数打包）
    // 那么EventLoop就可以具备发送数据的能力，也就
    // 可以将数据发给客户端
    
    if(_eventloop)
    {
        // function<void()> f = std::bind(&TcpConnection::send,this,msg);
        _eventloop->runInLoop(std::bind(&TcpConnection::send,this,msg));
    }
}

// 返回连接的描述字符串：包含本端地址和对端地址
string TcpConnection::toString()
{
    ostringstream oss;                 // 使用ostringstream构造字符串
    oss << _localAddr.ip() << ":"      // 本端IP地址
        << _localAddr.port() << "--->" // 本端端口号
        << _peerAddr.ip() << ":"       // 对端IP地址
        << _peerAddr.port();           // 对端端口号
    return oss.str();                  // 返回表示连接的字符串
}

// 获取本地地址：通过套接字获取本地网络地址信息
InetAddress TcpConnection::getLocalAddr()
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(struct sockaddr); // 地址结构的长度

    // 获取本地地址信息：调用getsockname函数
    int ret = getsockname(_sock.getfd(), (struct sockaddr *)&addr, &len); // 获取本地地址
    if (ret == -1)
    {
        perror("getsockname"); // 如果获取失败，打印错误信息
    }

    return InetAddress(addr); // 返回本地地址信息
}

// 获取对端地址：通过套接字获取对端的网络地址信息
InetAddress TcpConnection::getPeerAddr()
{
    struct sockaddr_in addr;
    socklen_t len = sizeof(struct sockaddr); // 地址结构的长度

    // 获取对端地址信息：调用getpeername函数
    int ret = getpeername(_sock.getfd(), (struct sockaddr *)&addr, &len); // 获取对端地址
    if (ret == -1)
    {
        perror("getpeername"); // 如果获取失败，打印错误信息
    }

    return InetAddress(addr); // 返回对端地址信息
}

// 三个回调的注册
void TcpConnection::setNewConnectionCallback(const TcpConnectionCallback &cb)
{
    _onNewConnection = cb;
}
void TcpConnection::setMessageCallback(const TcpConnectionCallback &cb)
{
    _onMessage = cb;
}
void TcpConnection::setCloseCallback(const TcpConnectionCallback &cb)
{
    _onClose = cb;
}

// 三个回调的执行
void TcpConnection::handleNewConnectionCallback()
{
    if(_onNewConnection)
    {
        // _onNewConnection(shared_ptr<TcpConnection>(this));  智能指针的误用，不同的智能指针托管的是同一个裸指针
        _onNewConnection(shared_from_this());
    }
    else
    {
        cout<<"_onNewConnection == nullptr!"<<endl;
        return;
    }
}
void TcpConnection::handleMessageCallback()
{
    if(_onMessage)
    {
        // _onMessage(shared_ptr<TcpConnection>(this));
        _onMessage(shared_from_this());
    }
    else
    {
        cout<<"_onMessage == nullptr!"<<endl;
        return ;
    }
}
void TcpConnection::handleCloseCallback()
{
    if(_onClose)
    {
        _onClose(shared_from_this());
    }
    else
    {
        cout<<"_onClose == nullptr"<<endl;
        return ;
    }
}

// 连接是否断开了
// 思路：只需要判断缓冲区中是否还有数据，用recv函数，第四个参数设置为：MSG_PEEK
bool TcpConnection::isClose()
{
    int connfd = _sock.getfd();
    char buf[1024] = {0};
    int ret = ::recv(connfd,buf,sizeof(buf),MSG_PEEK);
    return (ret==0);
}